package pl.edu.pw.ee.buildcity.charts;

import com.googlecode.charts4j.*;
import org.apache.commons.math.util.MathUtils;
import org.apache.log4j.Logger;
import pl.edu.pw.ee.buildcity.charts.models.BarChartModel;
import pl.edu.pw.ee.buildcity.entities.BuildActivity;
import pl.edu.pw.ee.buildcity.services.BuildActivityService;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

import static com.googlecode.charts4j.Color.BLACK;

/**
 * @author Mateusz
 * @since 2010-02-17
 */
public class ChartsGenerator {

	private static final Logger log = Logger.getLogger(ChartsGenerator.class);

	@Resource(name = "buildActivityService")
	private BuildActivityService buildActivityService;

	public static final int NUMBER_OF_ACTIVITIES_TO_FETCH = 20;
	private AxisStyle axisStyle = AxisStyle.newAxisStyle(BLACK, 13, AxisTextAlignment.CENTER);
	;

	/**
	 * @param buildDefName
	 * @return
	 */
	public String durationOfLatestBuildActivities(String buildDefName) {

		List<Plot> plots = new ArrayList<Plot>();

		List<List<Long>> durationsBeforeScale = new ArrayList<List<Long>>();

		List<BuildActivity> latestBuildActivities = buildActivityService.getLatestBuildActivities(buildDefName, NUMBER_OF_ACTIVITIES_TO_FETCH);
		for (BuildActivity bActivity : latestBuildActivities) {
			//	durationsBeforeScale.add(Arrays.asList(bActivity.getDuration()));
		}

		log.debug("Durations before scale: " + durationsBeforeScale);
		List<Data> durationsAfterScale = DataUtil.scale(durationsBeforeScale);

		int i = 0;
		for (Data scaledDuration : durationsAfterScale) {
			double duration = MathUtils.round(scaledDuration.getData()[0], 2);
			log.debug("Durations after scale: " + duration);
			BarChartModel chartModel = new BarChartModel(latestBuildActivities.get(i++).getResult(), duration);
			plots.add(chartModel.asPlot());
		}

		BarChart chart = GCharts.newBarChart(plots);

		AxisLabels durationInSeconds = AxisLabelsFactory.newNumericRangeAxisLabels(findMinDuration(durationsBeforeScale), findMaxDuration(durationsBeforeScale));
		durationInSeconds.setAxisStyle(axisStyle);
		chart.addYAxisLabels(durationInSeconds);

		chart.setTitle("Duration of latest build activities (in seconds)", BLACK, 16);
		chart.setGrid(100, NUMBER_OF_ACTIVITIES_TO_FETCH, 3, 2);
		chart.setSize(630, 300);

		return chart.toURLString();
	}

	private double findMinDuration(List<List<Long>> durationsBeforeScale) {
		long minDuration = Long.MAX_VALUE;

		for (List<Long> durations : durationsBeforeScale) {
			long duration = durations.get(0);

			if (duration < minDuration) {
				minDuration = duration;
			}
		}
		log.debug("min: " + minDuration);
		return minDuration;
	}

	private double findMaxDuration(List<List<Long>> durationsBeforeScale) {
		long maxDuration = Long.MIN_VALUE;

		for (List<Long> durations : durationsBeforeScale) {
			long duration = durations.get(0);

			if (duration > maxDuration) {
				maxDuration = duration;
			}
		}
		log.debug("max: " + maxDuration);
		return maxDuration;
	}

	void setBuildActivityService(BuildActivityService buildActivityService) {
		this.buildActivityService = buildActivityService;
	}
}
